#include "Common.h"
#include "Entity.h"
#include "Utils/pystring.h"
#include "Utils/Logger/Logger.h"

using namespace RayFrame;
using namespace std;
using namespace pystring;

IMPL_SINGLETON(EntityManager);

Entity::Entity(STRING extNames)
{
  m_enabled = true;
  m_extensions = (IEntityExtension**) malloc(sizeof(IEntityExtension**) * MAX_EXTENSION_COUNT);
  memset(m_extensions, 0, sizeof(IEntityExtension**)*MAX_EXTENSION_COUNT);

  vector<STRING> vecExtNames;
  split(extNames, vecExtNames);

  if(!vecExtNames.empty())
  {
    m_extensions = new IEntityExtension*[vecExtNames.size()];
    memset(m_extensions, 0, sizeof(IEntityExtension*) * vecExtNames.size());

    // find specified extensions
    vector<STRING>::iterator iter;
    int index = 0;
    for( iter = vecExtNames.begin(); iter!= vecExtNames.end(); iter++)
    {
      IEntityExtension* ext = EntityManager::InstanceRef().FindExtension(*iter);
      if(!ext)
      {
        LOG_ERROR2("Trying to create an invalid entity extension %s.",
                   iter->c_str());
      }
      m_extensions[index++] = ext;
    }

    EntityManager::InstanceRef().RegisterEntity(this);
  }
}

Entity::~Entity()
{
  // m_extensions is allocated and filled by entity manager
  free(m_extensions);
}

void RayFrame::Entity::OnUpdate( double timeElapsed )
{
  for(int i=0; i<MAX_EXTENSION_COUNT; i++)
    if(m_extensions[i])
      m_extensions[i]->OnUpdate(timeElapsed);
}

bool RayFrame::Entity::SetEnable( bool e /*= true*/ )
{
  m_enabled = e;
  return e;
}

bool RayFrame::Entity::GetEnable()
{
  return m_enabled;
}

void RayFrame::EntityManager::OnUpdate( double timeElapsed )
{
  for(IterEntity iter = m_entities.begin();
    iter != m_entities.end(); iter++)
  {
    if(iter->second->GetEnable())
      iter->second->OnUpdate(timeElapsed);
  }
}

bool RayFrame::EntityManager::RegisterExtension( IEntityExtension* extension )
{
  IterExtension iter = m_extensions.find(extension->GetTypeName());
  bool result = iter == m_extensions.end();

  m_extensions[extension->GetTypeName()] = extension;
  return result;
}

RayFrame::EntityId RayFrame::EntityManager::GenerateEntityId()
{
  // TODO: this is not thread safe!
  static EntityId counter = 0;
  assert(counter >= 0 );

  return ++counter;
}

bool RayFrame::EntityManager::RegisterEntity( Entity* entity )
{
  if(!entity)
  {
    LOG_ERROR1("Trying to register a entity with NULL pointer.");
    return false;
  }
  m_entities[entity->GetEntityId()] = entity;
  return true;
}

Entity* RayFrame::EntityManager::FindEntity( EntityId id )
{
  IterEntity iter = m_entities.find(id);
  if(iter != m_entities.end())
    return iter->second;
  else
    return NULL;
}

IEntityExtension* RayFrame::EntityManager::FindExtension( STRING extName )
{
  IterExtension iter = m_extensions.find(extName);
  if(iter != m_extensions.end())
    return iter->second;
  return NULL;
}

RayFrame::EntityManager::EntityManager()
{

}

RayFrame::EntityManager::~EntityManager()
{
  for(IterEntity iter = m_entities.begin();
    iter != m_entities.end(); iter++)
  {
    delete iter->second;
  }
}
